package ca.etsmtl.log430.lab2.data;

/**
 * This class defines the Driver object for the system. Besides the static
 * attributes, there are two lists maintained. deliveriesMadeList is a DeliveryList
 * object that maintains a list of courses that the student has taken.
 * deliveriesAssignedList is also a DeliveryList object that maintains a list of
 * deliveries assigned to the driver for the current day.
 * 
 * @author A.J. Lattanze, CMU
 * @version 1.4, 2012-May-31
 */

/* Modification Log
 ****************************************************************************
 *
 *v1.5, MA Bilodeau, 2012-June-21 - Various refactoring concerning restrictions to the insertion of deliveries
 *
 * v1.4, R. Champagne, 2012-May-31 - Various refactorings for new lab.
 * 
 * v1.3, R. Champagne, 2012-Feb-02 - Various refactorings for new lab.
 * 
 * v1.2, 2011-Feb-02, R. Champagne - Various refactorings, javadoc comments.
 *  
 * v1.1, 2002-May-21, R. Champagne - Adapted for use at ETS. 
 * 
 * v1.0, 12/29/99, A.J. Lattanze - Original version.

 ****************************************************************************/

public class Driver {


	private String lastName;
	private String firstName;
	private String driverID;
	private String driverType;
	private DeliveryList deliveriesMadeList = new DeliveryList();
	private DeliveryList deliveriesAssignedList = new DeliveryList();

	/**
	 * Registers a student for a course by adding a student for a course.
	 * 
	 * @param delivery
	 */
	public void assignDelivery(Delivery delivery) throws Exception{
		if(!isDeliveryLimitReached(delivery)){
			 if(!isTimeConflict(delivery)) {
				 getDeliveriesAssigned().addDelivery(delivery);
			 }
			 else{
				 throw new Exception("Time conflict occured.");
			 }
		}else{
			throw new Exception("Delivery limit for today reached.");
		}
	} // Register

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	public int factorielle(int n){
		return (n==0)?1:factorielle(n-1)*n;
	}

	public String getLastName() {
		return lastName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setDriverID(String driverID) {
		this.driverID = driverID;
	}

	public String getDriverID() {
		return driverID;
	}

	public void setType(String drivererType) {
		this.driverType = drivererType;
	}

	public String getType() {
		return driverType;
	}

	public void setDeliveriesMadeList(DeliveryList deliveriesMadeList) {
		this.deliveriesMadeList = deliveriesMadeList;
	}

	public DeliveryList getDeliveriesMadeList() {
		return deliveriesMadeList;
	}

	public void setDeliveriesAssigned(DeliveryList deliveriesAssigned) {
		this.deliveriesAssignedList = deliveriesAssigned;
	}

	public DeliveryList getDeliveriesAssigned() {
		return deliveriesAssignedList;
	}
	

	public boolean isDeliveryAssigned(String deliveryId){
		boolean found = false;
		boolean done = false;
		
		deliveriesAssignedList.goToFrontOfList();
		if(deliveriesAssignedList.findDelivery(deliveryId)==null)
			found = true;
		
		return found;
	}
	/**
	 * Compare delivery passed in parameters to the list of deliveries assigned to the driver. 
	 * If there is any time conflict, return true.
	 * @param delivery
	 * @return
	 */

	private boolean isTimeConflict(Delivery delivery){
		boolean done=false;
		int deliverySTime= delivery.getDesiredDeliveryTimeInMinutes();
		int deliveryETime= delivery.getDesiredDeliveryTimeInMinutes() + delivery.getEstimatedDeliveryDurationInMinutes();
		int curDeliverySTime,curDeliveryETime;

		Delivery currentDelivery;
		deliveriesAssignedList.goToFrontOfList();
		while(!done){
			currentDelivery = deliveriesAssignedList.getNextDelivery();
			if (currentDelivery == null) {
				done = true;
			} else {
				//need two integers, one corresponding to startTime, one to endTime,
				//for both delivery and currentDelivery
				curDeliverySTime = currentDelivery.getDesiredDeliveryTimeInMinutes();
				curDeliveryETime = currentDelivery.getDesiredDeliveryTimeInMinutes() + currentDelivery.getEstimatedDeliveryDurationInMinutes();
				if(isBetweenTime(deliverySTime,deliveryETime,curDeliverySTime,curDeliveryETime)){
					return true;
				}
			}
		}
		return false;
	}
	
	private boolean isBetweenTime(int timeToCompareStart, int timeToCompareEnd, int refTimeStart, int refTimeEnd){
		//there must not be any of the ref time comprised between the time to compare
		if((refTimeStart >= timeToCompareStart && refTimeStart <= timeToCompareEnd) || 
				(refTimeEnd <= timeToCompareEnd && refTimeEnd >= timeToCompareEnd)){
			return true;
		}
		return false;
	}
	
	/**
	 * Check if the next delivery will make the deliveries assigned to the driver today too long
	 * to complete (depending on his driver class)
	 * @param delivery
	 * @return
	 */
	private boolean isDeliveryLimitReached(Delivery delivery){
		boolean isAboveLimit;
		int limitDeliveryMinutes=0;
		
		if(driverType.equals("JNR")){
			limitDeliveryMinutes=720;
		}else if (driverType.equals("SNR")){
			limitDeliveryMinutes=480;
		}
		
		if(getDeliveryMinutes() + delivery.getEstimatedDeliveryDurationInMinutes()> limitDeliveryMinutes){
			isAboveLimit= true;
		}else{
			isAboveLimit=false;
		}
		return isAboveLimit;
	}
	
	/**
	 * Method that iterates through the list of deliveries and return the total estimated time to complete them.
	 * @return
	 */
	private int getDeliveryMinutes(){
		boolean done=false;
		Delivery currentDelivery;
		int totalNbMinutes=0;
		deliveriesAssignedList.goToFrontOfList();
		while(!done){
			currentDelivery = deliveriesAssignedList.getNextDelivery();
			if (currentDelivery == null) {
				done = true;
			} else {
				totalNbMinutes+=currentDelivery.getEstimatedDeliveryDurationInMinutes();
			} // if
		}
		return totalNbMinutes;
	}

} // Driver class